#ifndef STATE_MACHINE_HPP
#define STATE_MACHINE_HPP

#include "log.h"
#include "stepper.h"
#include "limit_switch.h"
#include "Ttask.h"
#include <queue>
#include "vl6180x_api.h" 
#include "vl6180x_sample_plat.h"
//#define MyDev_Init(dev) (dev=0x52)
// Forward declarations to avoid circular dependencies
// Forward declarations to avoid circular dependencies
class State;
class IDLE;
class CONFIRMING;
class TRANSFERRING;
class PULLING;
class FULL_LOAD; // Declare the new state class

extern LOG *log_1;
extern LOG *log_2;
extern LimitLayer LimitLayerObj;

enum class Event {
  DETECT_T,
  CONFIRM_NONE,
  CONFIRM_OK,
  LIMITATION_1, //<--
  LIMITATION_2, //-->
  DETECED,
  CAPTURE_T,
  CAPTURE_C,
  RUN,
  PULLING,
  ROTATE,
  NONE_
};


enum class TRANSFER {
  FORWARD,  //<--
  BACKWARD, //-->
  NONE_
};

// Base class for all states in the state machine
class State {
public:
  virtual ~State() = default;
  virtual void onEnter();                             // Called when entering a state
  virtual void onExit();                              // Called when exiting a state
  virtual State* handleEvent(Event event, int param); // Handle an event and return next state if transition is needed
};

// Concrete states
class IDLE : public State {
public:
  void onEnter() override;
  void onExit() override;
  State* handleEvent(Event event, int param) override;
private:
  TTASK task;
};

class CONFIRMING : public State {
public:
  explicit CONFIRMING(TRANSFER param) : param_(param) {}
  void onEnter() override;
  void onExit() override;
  State* handleEvent(Event event, int param) override;

private:
  TRANSFER param_;
};

class TRANSFERRING : public State {
public:
  explicit TRANSFERRING(TRANSFER param) : param_(param) {}
  void onEnter() override;
  void onExit() override;
  State* handleEvent(Event event, int param) override;

private:
  TTASK task[9];
  TTASK STARTtask[2];

  TRANSFER param_;
};

// PULLING
class PULLING : public State {
public:
  explicit PULLING(int param) : param_(param) {}
  void onEnter() override;
  void onExit() override;
  State *handleEvent(Event event, int param) override;

private:
  bool flag = false;
  int param_;
  int counter=0;
  TTASK task;
  TTASK single_shot;

};

class ROTATE : public State {
public:
  explicit ROTATE(int param) : param_(param) {}
  void onEnter() override;
  void onExit() override;
  State *handleEvent(Event event, int param) override;

private:
  int param_;
};

// State Machine class that manages state transitions
class StateMachine {
private:
    std::queue<std::pair<Event, int>> eventQueue;
    State* currentState = nullptr; // Pointer to the current state

public:
    void enqueueEvent(Event event, int param = 0);
    void processEvents();
    void start(State* initialState);    // Initialize the state machine with an initial state
    void processEvent(Event event, int param); // Process a single event
};

#endif // STATE_MACHINE_HPP 